local socket = require "socket"

function download (host, file)
	local c = assert(socket.connect(host, 80))
	local count = 0 	-- read bytes
	local request = string.format(
		"GET %s HTTP/1.0\r\nhost: %s\r\n\r\n", file, host)
	c:send(request)
	while true do
		local s, status = receive(c)
		count = count + #s
		if status == "closed" then break end
	end
	c:close()
	print(file, count)
end

function receive (connection)
	connection:settimeout(0) 	-- non-block
	local s, status, partial = connection:receive(2^10)
	if status == "timeout" then
		coroutine.yield(connection)
	end
	return s or partial, status
end

tasks = {} 	-- list of all active tasks

function get (host, file)
	-- create a coroutine for task
	local co = coroutine.wrap(function ()
		download(host, file)
	end)
	-- add the task to list
	table.insert(tasks, co)
end

function dispatch ()
	local i = 1
	local timedout = {}
	while true do
		if tasks[i] == nil then 	-- no other tasks
			if tasks[1] == nil then 	-- list is empty
				break
			end
			i = 1 	
			timedout = {}
		end
		local res = tasks[i]() 	-- run a task
		if not res then 	-- task is end
			table.remove(tasks, i)
		else
			i = i + 1 	-- next task
			timedout[#timedout + 1] = res
			if #timedout == #tasks then 	-- all tasks are blocked
				socket.select(timedout) 		-- block until one task's state has change
			end
		end
	end
end

get("www.lua.org", "/ftp/lua-5.3.2.tar.gz")
get("www.lua.org", "/ftp/lua-5.3.1.tar.gz")
get("www.lua.org", "/ftp/lua-5.3.0.tar.gz")
get("www.lua.org", "/ftp/lua-5.2.4.tar.gz")
get("www.lua.org", "/ftp/lua-5.2.3.tar.gz")

dispatch() 	-- main loop
